#include <lxMessege.h>
#include <typescommon.h>

int msgDtPackRmtId(struct msgDtStct *msgdata, long inRmt)
{
    if (!msgdata)
    {
        logerror("");
        return -1;
    }
    msgdata->rmtId = inRmt;
    return 0;
}
int msgDtPackCmd(struct msgDtStct *msgdata, uint16_t incmd)
{
    if (!msgdata)
    {
        logerror("");
        return -1;
    }
    msgdata->msgCmd = incmd;
    return 0;
}
static int msgDtPackSndId(struct msgDtStct *msgdata, long insnd)
{
    if (!msgdata)
    {
        logerror("");
        return -1;
    }
    msgdata->sndId = insnd;
    return 0;
}
int msgDtPackMem(struct msgDtStct *msgdata, const void *indata, uint16_t dsize)
{
    if (!msgdata)
    {
        logerror("");
        return -1;
    }
    if (sizeof(msgdata->msgData) < dsize)
    {
        logerror("msg size err:%d", dsize);
        return -1;
    }
    memcpy(msgdata->msgData, indata, dsize);
    msgdata->msgSize = dsize;
    return dsize;
}
int msgDtPackStr(struct msgDtStct *msgdata, const char *indata)
{
    return msgDtPackMem(msgdata, indata, strlen(indata));
}
int msgDtPackIdMem(struct msgDtStct *msgdata, const void *indata, uint16_t dsize, long inRmt, uint16_t incmd)
{
    if (!msgdata)
    {
        logerror("");
        return -1;
    }
    msgDtPackRmtId(msgdata, inRmt);
    // msgDtPackSndId(msgdata, 0);
    msgDtPackCmd(msgdata, incmd);
    return msgDtPackMem(msgdata, indata, dsize);
}
int msgDtPackIdStr(struct msgDtStct *msgdata, const char *indata, long inRmt, uint16_t incmd)
{
    return msgDtPackIdMem(msgdata, indata, strlen(indata), inRmt, incmd);
}

int msgOptInit(struct msgOptStct *msgopt, key_t inkey, long inId)
{
    if (!msgopt)
    {
        logerror("");
        return -1;
    }
    msgopt->msgkey = inkey;
    msgopt->myId = inId;
    msgopt->msgfd = msgget(msgopt->msgkey, 0666 | IPC_CREAT);
    logdebug("%d, %d", msgopt->msgkey, msgopt->msgfd);
    return msgopt->msgfd;
}
int msgOptQuit(struct msgOptStct *msgopt)
{
    if(msgopt->msgfd > 0)
    {
        msgctl(msgopt->msgfd, IPC_RMID, NULL);
        msgopt->msgfd = -1;
    }
    return 0;
}
// rmtId remote key id
int msgOptSend(struct msgOptStct *msgopt, struct msgDtStct *indata)
{
    if (!msgopt || !indata)
    {
        logerror("");
        return -1;
    }
    msgDtPackSndId(indata, msgopt->myId);
    logdebug("c snd[rmt=%ld,snd=%ld,cmd=%d,size=%d]data=%s", indata->rmtId, indata->sndId, indata->msgCmd, indata->msgSize, indata->msgData);
    if (msgsnd(msgopt->msgfd, indata, ONE_MSG_HEAD_LEN + indata->msgSize, IPC_NOWAIT) < 0)
    {
        logerror("send error %d", msgopt->msgkey);
        return -2;
    }
    return indata->msgSize;
}
int msgOptSendMem(struct msgOptStct *msgopt, const void *indata, uint16_t dsize, long inRmt, uint16_t incmd)
{
    struct msgDtStct tmpdata;
    if (!msgopt || !indata)
    {
        logerror("");
        return -1;
    }
    if(msgDtPackIdMem(&tmpdata, indata, dsize, inRmt, incmd) < 0)
    {
        logerror("");
        return -1;
    }
    return msgOptSend(msgopt, &tmpdata);
}
int msgOptSendStr(struct msgOptStct *msgopt, const char *indata, long inRmt, uint16_t incmd)
{
    return msgOptSendMem(msgopt, indata, strlen(indata), inRmt, incmd);
}
// messege operator receive
int msgOptRcv(struct msgOptStct *msgopt, struct msgDtStct *indata)
{
    if (!msgopt || !indata)
    {
        logerror("");
        return -1;
    }
    int rcvlen = msgrcv(msgopt->msgfd, indata, sizeof(struct msgDtStct), msgopt->myId, IPC_NOWAIT);
    if (rcvlen > 0)
    {
        return indata->msgSize;
    }
    return -2;
}


#if 0
#include <typescommon.h>
#include <genrand.h>
#include <pthread.h>
#include <sys/msg.h>
#include <cstring.h>
#include <threadExcuter.h>
#include <lxMessege.h>

#define MES_CHECK_KEY_ID 12345
#define MES_CHECK_RCV_ID_A 11111
#define MES_CHECK_RCV_ID_B 11112
#define MES_CHECK_RCV_ID_C 11113
void *MsgCheckThread(void *ptr)
{
    struct msgDtStct tmpDataSend, tmpDataRcv;
    struct msgOptStct tmpMsgC;
    struct thrdExeStct *tmpthrd = (struct thrdExeStct *)ptr;
    msgOptInit(&tmpMsgC, MES_CHECK_KEY_ID, MES_CHECK_RCV_ID_C);
    logdebug("c thread begin");
    while (tmpthrd->threadRunflag)
    {
        usleep(5000);
        if (msgOptRcv(&tmpMsgC, &tmpDataRcv) < 0)
        {
            continue;
        }
        logdebug("c rcv[rmt=%ld,snd=%ld,size=%d]data=%s", tmpDataRcv.rmtId, tmpDataRcv.sndId, tmpDataRcv.msgSize, tmpDataRcv.msgData);
        msgDtPackIdStr(&tmpDataSend, "c send to back", tmpDataRcv.sndId);
        msgOptSend(&tmpMsgC, &tmpDataSend);
        logdebug("c snd[rmt=%ld,snd=%ld,size=%d]data=%s", tmpDataSend.rmtId, tmpDataSend.sndId, tmpDataSend.msgSize, tmpDataSend.msgData);
    }
    return NULL;
}

int main()
{
    struct msgDtStct tmpDataSend, tmpDataRcv;
    struct msgOptStct tmpMsgA;
    struct msgOptStct tmpMsgB;
    msgOptInit(&tmpMsgA, MES_CHECK_KEY_ID, MES_CHECK_RCV_ID_A);
    msgOptInit(&tmpMsgB, MES_CHECK_KEY_ID, MES_CHECK_RCV_ID_B);
    struct thrdExeStct tmpthrd;
    thrdExeInit(&tmpthrd, MsgCheckThread, NULL);
    thrdExeBegin(&tmpthrd);
    sleep(1);
    for (int i = 0; i < 6; i++)
    {
        if (i == 0)
        {
            msgDtPackIdStr(&tmpDataSend, "a send to a", tmpMsgA.myId);
            msgOptSend(&tmpMsgA, &tmpDataSend);
        }
        else if (i == 1)
        {
            msgDtPackIdStr(&tmpDataSend, "a send to b", tmpMsgB.myId);
            msgOptSend(&tmpMsgA, &tmpDataSend);
        }
        else if (i == 2)
        {
            msgDtPackIdStr(&tmpDataSend, "b send to a", tmpMsgA.myId);
            msgOptSend(&tmpMsgB, &tmpDataSend);
        }
        else if (i == 3)
        {
            msgDtPackIdStr(&tmpDataSend, "b send to b", tmpMsgB.myId);
            msgOptSend(&tmpMsgB, &tmpDataSend);
        }
        else if (i == 4)
        {
            msgDtPackIdStr(&tmpDataSend, "a send to c", MES_CHECK_RCV_ID_C);
            msgOptSend(&tmpMsgA, &tmpDataSend);
        }
        else if (i == 5)
        {
            msgDtPackIdStr(&tmpDataSend, "b send to c", MES_CHECK_RCV_ID_C);
            msgOptSend(&tmpMsgB, &tmpDataSend);
        }
        logdebug("main snd[rmt=%ld,snd=%ld,size=%d]data=%s", tmpDataSend.rmtId, tmpDataSend.sndId, tmpDataSend.msgSize, tmpDataSend.msgData);
        // usleep(10000);
        usleep(100000);
        if (msgOptRcv(&tmpMsgA, &tmpDataRcv) < 0)
        {
            logdebug("a no data");
        }
        else
        {
            logdebug("a rcv[rmt=%ld,snd=%ld,size=%d]data=%s", tmpDataRcv.rmtId, tmpDataRcv.sndId, tmpDataRcv.msgSize, tmpDataRcv.msgData);
        }
        if (msgOptRcv(&tmpMsgB, &tmpDataRcv) < 0)
        {
            logdebug("b no data");
        }
        else
        {
            logdebug("b rcv[rmt=%ld,snd=%ld,size=%d]data=%s", tmpDataRcv.rmtId, tmpDataRcv.sndId, tmpDataRcv.msgSize, tmpDataRcv.msgData);
        }
    }
    thrdExeQuit(&tmpthrd);
    return -1;
}

#endif